#include <stdio.h>
#include <math.h>
#include <limits.h>

/* int 4字节整数类型
 *
 * */


// 有效数据位数
int validBits(int a) {
    int len = sizeof(a) * 8;
    int all1 = 0xffffffff;
    for (int i = 0; i < len; ++i) {
        if ((all1 << i) == 0) {
            return i;
        }
    }
    return 32;
}

// 打印二进制字符串
void printBinaryStr(int a) {
    int len = sizeof(a) * 8;
    int all1 = 0xffffffff;
    char str[34] = {0};
    for (int i = 0; i < len; ++i) {
        str[31-i] = ((unsigned)((1 << i) & a) >> i) == 0 ? '0' : '1';
        
    }
    str[32] = '\n';
    printf("int二进制：%s", str);
}

// 打印二进制字符串
void printBinaryStr2(float f) {
    int * intPtr = (int *)&f;
    int a = *intPtr;
    int len = sizeof(a) * 8;
    int all1 = 0xffffffff;
    char str[34] = {0};
    for (int i = 0; i < len; ++i) {
        str[31-i] = ((unsigned)((1 << i) & a) >> i) == 0 ? '0' : '1';
        
    }
    str[32] = '\n';
    printf("float二进制：%s", str);
}

int main() {
    // 整型的底层存储为补码
    int a = 2; // 0x2
    printBinaryStr(a);
    printBinaryStr2(*(float*)&a);
    float f = (float)a;
    printBinaryStr2(f);
    printBinaryStr(*(int*)&f);
    printf("%x\n", a); // 0x2
    printf("%d\n", ~a + 1); // -2 对底层存储取反加1的效果就是对字面量取相反数

    // 正负相加，会进位，不会溢出，进位直接忽略即可，不影响计算结果
    // 正正相加，不会进位，会溢出，计算结果超过0x7fffffff（正数最大值）就是溢出，符号变为负
    // 负负相加，会进位，会溢出，
    printf("%x\n", 0x7fffffff + 1); // 最大值加1得到最小值 0x80000000
    printf("max int: %d\n", 0x7fffffff); // 2147483647
    printf("min int: %d\n", 0x7fffffff + 1); // -2147483648  由此可看出，o应该算作正数，这样正负数的个数相等
    long b = pow(2, 35); //2的35次幂 超过MAX_INT，就取MAX_INT
    printf("%d\n", b);
    printf("%d\n", sizeof(long)); // 4 ANSI规定，long长度>=int长度。在具体的编译系统中，有些是long长度=int长度，如VC++。有些是long长度>int长度，如TC。
    printf("%d\n", sizeof(int)); // 4
    printf("%d\n", 1L << 31); // -2147483648
    printf("%d\n", (1 << 31) - 1); // INT_MIN减1（加-1）得到INT_MAX

    // 无符号数的加减法和有符号数的加减法，用的是相同的汇编指令，二者的区别只不过是将二进制位翻译成十进制字面量后不一样了
    // 判断两个同正或同负的数相加是否溢出的方法是计算结果的符号是否变了，而判断无符号数a和b相加是否溢出的方法是(UNSIGNED_MAX - a > b)
    printf("sizeof unsigned: %d\n", sizeof(unsigned)); //4
    printf("%d\n", (unsigned)-1); // -1
    printf("%u\n", -1); // 4294967295 无符号数的最大值
    printf("%d\n", INT_MAX); // 2147483647
    printf("%d\n", INT_MIN); // -2147483648

    // 有符号数和无符号数的加减法运算，对底层汇编指令来说是无感知的，同等对待，只不过是要将计算结果解释为什么样的数罢了


    return 0;
}

